/******************************************************************************
*	device/hid/report.h
*	 by Alex Chadwick
*
*	A light weight implementation of the USB protocol stack fit for a simple
*	driver.
*
*	device/hid/report.h contains definitions relating to human interface
*	device reports, used to communicate the functionality of any given hid
*	device.
******************************************************************************/
#ifndef _DEVICE_HID_REPORT_H
#define _DEVICE_HID_REPORT_H
#include <types.h>

#include <device/hid/hid.h>

//------------------------------------------------------------------------------
/**
	\brief An item in an hid report descriptor.

	The hid report item sturcture defined in the USB HID 1.11 manual in
	6.2.2.2. There are two such types defined here, long and short. Since long
	is based upon short. So we can resuse the structure to this effect.
*/
typedef
	enum HidReportTag {
		TagMainInput              = 0x20,
		TagMainOutput             = 0x24,
		TagMainFeature            = 0x2C,
		TagMainCollection         = 0x28,
		TagMainEndCollection      = 0x30,
		TagGlobalUsagePage        = 0x01,
		TagGlobalLogicalMinimum   = 0x05,
		TagGlobalLogicalMaximum   = 0x09,
		TagGlobalPhysicalMinimum  = 0x0D,
		TagGlobalPhysicalMaximum  = 0x11,
		TagGlobalUnitExponent     = 0x15,
		TagGlobalUnit             = 0x19,
		TagGlobalReportSize       = 0x1D,
		TagGlobalReportId         = 0x21,
		TagGlobalReportCount      = 0x25,
		TagGlobalPush             = 0x29,
		TagGlobalPop              = 0x2D,
		TagLocalUsage             = 0x02,
		TagLocalUsageMinimum      = 0x06,
		TagLocalUsageMaximum      = 0x0A,
		TagLocalDesignatorIndex   = 0x0E,
		TagLocalDesignatorMinimum = 0x12,
		TagLocalDesignatorMaximum = 0x16,
		TagLocalStringIndex       = 0x1E,
		TagLocalStringMinimum     = 0x22,
		TagLocalStringMaximum     = 0x26,
		TagLocalDelimiter         = 0x2A,
		TagLong                   = 0x3F,
	}
HidReportTag;

typedef
	struct HidReportItem {
		unsigned     Size : 2;  // @0 (Value is 1 << (size - 1))
		HidReportTag Tag  : 6;  // @2
	}
HidReportItem;

//------------------------------------------------------------------------------
/**
	\brief A main input, output or feature in an hid report descriptor.

	The hid main input, output or feature item sturcture defined in the USB HID
	1.11 manual in 6.2.2.4.
*/
typedef
	struct HidMainItem {
		bool     Constant      :  1;  // @0  0=Data           1=Constant
		bool     Variable      :  1;  // @1  0=Array          1=Variable
		bool     Relative      :  1;  // @2  0=Absolute       1=Relative
		bool     Wrap          :  1;  // @3  0=NoWrap         1=Wrap
		bool     NonLinear     :  1;  // @4  0=Linear         1=NonLinear
		bool     NoPreferred   :  1;  // @5  0=PreferredState 1=NoPreferred
		bool     Null          :  1;  // @6  0=NoNull         1=NullState
		bool     Volatile      :  1;  // @7  0=NonVolatile    1=Volatile      [Inputs cannot be volatile]
		bool     BufferedBytes :  1;  // @8  0=BitField       1=BufferedBytes
		unsigned _reserved9_31 : 23;  // @9
	}
HidMainItem;

//------------------------------------------------------------------------------
/**
	\brief A main collection index in an hid report descriptor.

	The hid main collection index used in the collection item defined in the
	USB HID 1.11 manual in 6.2.2.4.
*/
typedef
	enum HidMainCollection {
		Physical      = 0,
		Application   = 1,
		Logical       = 2,
		Report        = 3,
		NamedArray    = 4,
		UsageSwitch   = 5,
		UsageModifier = 6,
	}
HidMainCollection;

//------------------------------------------------------------------------------
/**
	\brief Values of the hid page usage field in a report.

	Values that the hid page usage can take in a hid report descriptor. Defined
	in section 3 table 1 of the HID 1.11 usage tables.
*/
typedef
	enum HidUsagePage {
		GenericDesktopControl =  1,
		SimulationControl     =  2,
		VrControl             =  3,
		SportControl          =  4,
		GameControl           =  5,
		GenericDeviceControl  =  6,
		KeyboardControl       =  7,
		Led                   =  8,
		Button                =  9,
		Ordinal               = 10,
		Telephony             = 11,
		Consumer              = 12,
		Digitlizer            = 13,
		PidPage               = 15,
		Unicode               = 16,
		_HidUsagePage         = 0xFFFF,
	}
HidUsagePage;

//------------------------------------------------------------------------------
/**
	\brief Values of the hid desktop page usage in a report.

	Values that usage numbers in the desktop page represent. Defined in
	section 4 table 6 of the HID 1.11 usage tables. Only items below 0x48 are
	included here for brevity.
*/
typedef
	enum HidUsagePageDesktop {
		DesktopPoint                = 1,
		DesktopMouse                = 2,
		DesktopJoystick             = 4,
		DesktopGamePad              = 5,
		DesktopKeyboard             = 6,
		DesktopKeypad               = 7,
		DesktopMultiAxisController  = 8,
		DesktopTablePcControl       = 9,
		DesktopX                    = 0x30,
		DesktopY                    = 0x31,
		DesktopZ                    = 0x32,
		DesktopRX                   = 0x33,
		DesktopRY                   = 0x34,
		DesktopRZ                   = 0x35,
		DesktopSlider               = 0x36,
		DesktopDial                 = 0x37,
		DesktopWheel                = 0x38,
		DesktopHatSwitch            = 0x39,
		DesktopCountedBuffer        = 0x3A,
		DesktopByteCount            = 0x3B,
		DesktopMotionWakeup         = 0x3C,
		DesktopStart                = 0x3D,
		DesktopSelect               = 0x3E,
		DesktopVX                   = 0x40,
		DesktopVY                   = 0x41,
		DesktopVZ                   = 0x42,
		DesktopVbrX                 = 0x43,
		DesktopVbrY                 = 0x44,
		DesktopVbrZ                 = 0x45,
		DesktopVno                  = 0x46,
		DesktopFeatureNotification  = 0x47,
		DesktopResolutionMultiplier = 0x48,
		_HidUsagePageDesktopDummy   = 0xFFFF,
	}
HidUsagePageDesktop;

//------------------------------------------------------------------------------
/**
	\brief Values of the hid keyboard page usage in a report.

	Values that usage numbers in the keyboard page represent. Defined in
	section 10 table 12 of the HID 1.11 usage tables. Key definitions are not
	included here, as this driver, being deliberately akward, does not handle
	them.
*/
typedef
	enum HidUsagePageKeyboard {
		KeyboardErrorRollOver  = 1,
		KeyboardPostFail       = 2,
		KeyboardErrorUndefined = 3,
		KeyboardLeftControl    = 0xE0,
		KeyboardLeftShift      = 0xE1,
		KeyboardLeftAlt        = 0xE2,
		KeyboardLeftGui        = 0xE3,
		KeyboardRightControl   = 0xE4,
		KeyboardRightShift     = 0xE5,
		KeyboardRightAlt       = 0xE6,
		KeyboardRightGui       = 0xE7,
		_HidUsagePageKeyboard  = 0xFFFF,
	}
HidUsagePageKeyboard;

//------------------------------------------------------------------------------
/**
	\brief Values of the hid led page usage in a report.

	Values that usage numbers in the keyboard page represent. Defined in
	section 11 table 13 of the HID 1.11 usage tables.
*/
typedef
	enum HidUsagePageLed {
		LedNumberLock    = 1,
		LedCapsLock      = 2,
		LedScrollLock    = 3,
		LedCompose       = 4,
		LedKana          = 5,
		LedPower         = 6,
		LedShift         = 7,
		LedMute          = 9,
		_HidUsagePageLed = 0xFFFF,
	}
HidUsagePageLed;

//------------------------------------------------------------------------------
/**
	\brief A full HID usage tag.

	A full HID usage with both the page and the tag represented in the order it
	can appear in HID report descriptors.
*/
typedef
	struct HidFullUsage {
		union {
			HidUsagePageDesktop  Desktop  : 16;
			HidUsagePageKeyboard Keyboard : 16;
			HidUsagePageLed      Led      : 16;
		};
		HidUsagePage             Page     : 16;
	}
HidFullUsage;

//------------------------------------------------------------------------------
/**
	\brief A HID field units declaration.

	The units of a HID field. This declaration allows the defintion of many SI
	units.
*/
typedef
	enum HuSystem {
		SystemNone       = 0,
		StandardLinear   = 1,  // Centimeter, Gram, Second, Kelvin,     Ampere, Candela
		StandardRotation = 2,  // Radian,     Gram, Second, Kelvin,     Ampere, Candela
		EnglishLinear    = 3,  // Inch,       Slug, Second, Fahrenheit, Ampere, Candela
		EnglishRotation  = 4,  // Degree,     Slug, Second, Fahrenheit, Ampere, Candela
	}
HuSystem;

typedef
	struct HidUnit {
		HuSystem System            : 4;
		signed   Length            : 4;
		signed   Mass              : 4;
		signed   Time              : 4;
		signed   Temperature       : 4;
		signed   Current           : 4;
		signed   LuminousIntensity : 4;
		unsigned _reserved28_31    : 4;
	}
HidUnit;

//------------------------------------------------------------------------------
/**
	\brief A parsed report field, with value.

	A representation of a fully parsed report field complete with value for
	easy retrieval and setting of values.
*/
typedef
	struct HidParserField {
		u8           Size;               // Bit-size of this field. For arrays, this is per element.
		u8           Offset;             // Bit-offset of this field into the report
		u8           Count;              // Number of fields in array fields
		HidMainItem  Attributes ALIGN4;  // Field attributes
		HidFullUsage Usage;              // For array elements, this is the first usage
		                                 // ...it is assumed sequential values have sequential usage.
		HidFullUsage PhysicalUsage;      // Usage of the physical connection this device is in, if present.
		s32          LogicalMinimum;     // The minimum value of this field.
		s32          LogicalMaximum;     // The maximum value of this field.
		s32          PhysicalMinimum;    // The minimum physical quantity represented by this field.
		s32          PhysicalMaximum;    // The maximum physical quantity represented by this field.
		HidUnit      Unit;               // The units of this field's physical quantity.
		s32          UnitExponent;       // The base 10 exponenet of this field's physical quantity.
		union {  // Field value.  The value is "logical" not "sign extended"
			u8   U8;
			s8   S8;
			u16  U16;
			s16  S16;
			u32  U32;
			s32  S32;
			bool Bool;
			void *Pointer;
		} Value;
	}
HidParserField;

//------------------------------------------------------------------------------
/**
	\brief A parsed report, with values.

	A representation of a fully parsed report complete with value fields for
	easy retrieval and setting of values.
*/
typedef
	struct HidParserReport {
		u8             Index;            // Which report this is in the parser result.
		u8             FieldCount;       // Number of fields in this report
		u8             Id;               // Either 0 or The report ID
		HidReportType  Type;             // Report type
		u8             ReportLength;     // Byte-length of this report
		u8             *ReportBuffer;    // Either NULL or The Last received report
		HidParserField Fields[] ALIGN4;  // Sequential store of the fields
	}
HidParserReport;

//------------------------------------------------------------------------------
/**
	\brief A parsed report descriptor, with values.

	A representation of a fully parsed report descriptor complete with value
	fields for easy retrieval and setting of values.
*/
typedef
	struct HidParserResult {
		HidFullUsage    Application;       // Application collection with a usage for report
		u8              ReportCount;       // Number of reports
		u8              Interface;         // HID interface number
		HidParserReport *Report[] ALIGN4;  // Array of report pointers
	}
HidParserResult;

//------------------------------------------------------------------------------
/**
	\brief Retrieves a value from a field.

	Reads the current value at a given index in a HID field.
*/
s32 HidGetFieldValue(HidParserField *field, u32 index);

#endif // _DEVICE_HID_REPORT_H
